package com.demo.gulimall.auth.controller;

import com.demo.gulimall.auth.component.SmsComponent;
import com.demo.gulimall.auth.entity.Member;
import com.demo.gulimall.auth.exception.OptionException;
import com.demo.gulimall.auth.mapper.MemberMapper;
import com.demo.gulimall.auth.service.MemberService;
import com.demo.gulimall.auth.vo.MemberLoginVo;
import com.demo.gulimall.auth.vo.MemberRegVo;
import com.demo.gulimall.common.constant.AuthConstant;
import com.demo.gulimall.common.exception.BizCodeEnume;
import com.demo.gulimall.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Chen Yuan
 * @create 2023-06-13  16:38
 */
@Slf4j
@RestController
@RequestMapping("/login")
public class LoginController {
	@Autowired
	private SmsComponent smsComponent;

	@Autowired
	private StringRedisTemplate redisTemplate;

	@Autowired
	private MemberService memberService;

	@Autowired
	private MemberMapper memberMapper;

	@GetMapping("/sms/sendcode")
	public R sendCode(@RequestParam("phone") String phone) {
		String redisKey = AuthConstant.SMS_CODE_CACHE_PREFIX + phone;
		// 接口防刷, 防止 60s 内不断发送
		String value = redisTemplate.opsForValue().get(redisKey);
		if (StringUtils.isNotEmpty(value)) {
			// 获取上一次发送验证码的时间, 如果时间间隔在 60s 内则不发
			long currentTime = Long.parseLong(value.split("_")[1]);
			if (System.currentTimeMillis() - currentTime < (60 * 1000)){
				// 60s 内不能再发, 直接返回
				return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(), BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
			}
		}

		// 随机生成验证码
		String code = UUID.randomUUID().toString().substring(0, 6);

		// 验证码再次校验, Redis 缓存, 存入 Redis 之前在 code 后面拼上时间
		String redisValue = code + "_" + System.currentTimeMillis();
		redisTemplate.opsForValue().set(redisKey, redisValue, 10, TimeUnit.MINUTES);

		// 发送验证码
		smsComponent.sendCode(phone, code);
		log.info("--> 短信验证码发送成功 - phone:{}, code:{}", phone, code);
		return R.ok("发送成功");
	}


	@PostMapping("/member/reg")
	public R memberReg(@RequestBody MemberRegVo memberReg){
		// 校验验证码
		String redisKey = AuthConstant.SMS_CODE_CACHE_PREFIX + memberReg.getPhone();
		String value = redisTemplate.opsForValue().get(redisKey);
		if (StringUtils.isEmpty(value)) {
			return R.error("验证码已过期");
		}
		log.info(value);
		value = value.split("_")[0];
		if (!Objects.equals(value, memberReg.getCode())){
			return R.error("验证码输入错误");
		}
		// 校验成功, 则删除
		redisTemplate.delete(redisKey);

		// 开始真正的注册操作
		try {
			memberService.memberReg(memberReg);
		} catch (OptionException e) {
			log.info("--> 注册异常 - msg:{}", e.getMessage());
			return R.error(e.getMessage());
		}

		return R.ok();
	}


	// 最简单的登录
	@PostMapping("/member/login")
	public R memberLogin(@RequestBody MemberLoginVo memberLogin, HttpSession session){
		Member member = memberMapper.selectMemberByUserName(memberLogin.getUserName());
		if (null == member) {
			return R.error("用户不存在");
		}

		BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
		boolean matches = passwordEncoder.matches(memberLogin.getPassword(), member.getPassword());

		if (matches) {
			// 登录成功将用户信息保存到 Session
			session.setAttribute(AuthConstant.LOGIN_USER, member);
			return R.ok("登录成功");
		}else {
			return R.error("密码错误");
		}
	}
}
